package com.csf.service.impl;

import com.csf.entity.DiscussPost;
import com.csf.service.DiscussPostService;
import com.csf.service.ElasticSearchService;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class ElasticSearchServiceImpl implements ElasticSearchService {

    @Autowired
    private DiscussPostService disService;

    @Autowired
    private ElasticsearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Override
    public void saveDiscussPostEs(DiscussPost discussPost) {
        if (discussPost != null){
            repository.save(discussPost);
        }
    }

    @Override
    public void deleteDiscussPostEs(DiscussPost discussPost) {
            repository.delete(discussPost);
    }

    @Override
    public Page<DiscussPost> findDiscussPostEs(String keyWord, int initRows, int limit) {
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
//                查找的字段，在哪里面找
                .withQuery(QueryBuilders.multiMatchQuery(keyWord,"title","content"))
//                排序
                .withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
//               分页
                .withPageable(PageRequest.of(initRows,limit))
//                给搜索的关键字加颜色
                .withHighlightFields(
                        new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),
                        new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")
                ).build();

        return template.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {
//                首先获取所有相关的目标
                SearchHits hit = response.getHits();
                if (hit.getTotalHits() <=0){
                    return null;
                }
//                通过遍历重新获取帖子数据，并且将title和content设置为有前后缀的数据
                List<DiscussPost> list = new ArrayList<>();
                for (SearchHit searchHit : hit) {
                    DiscussPost discussPost = new DiscussPost();

                    String id = searchHit.getSourceAsMap().get("id").toString();
                    discussPost.setId(Integer.parseInt(id));

                    String userId = searchHit.getSourceAsMap().get("userId").toString();
                    discussPost.setUserId(Integer.parseInt(userId));

                    String title = searchHit.getSourceAsMap().get("title").toString();
                    discussPost.setTitle(title);

                    String content = searchHit.getSourceAsMap().get("content").toString();
                    discussPost.setContent(content);

                    String status = searchHit.getSourceAsMap().get("status").toString();
                    discussPost.setStatus(Integer.valueOf(status));

                    String createTime = searchHit.getSourceAsMap().get("createTime").toString();
                    discussPost.setCreateTime(new Date(Long.valueOf(createTime)));

                    String commentCount = searchHit.getSourceAsMap().get("commentCount").toString();
                    discussPost.setCommentCount(Integer.valueOf(commentCount));

//                    处理高亮
                    HighlightField highlightField = searchHit.getHighlightFields().get("title");
                    if (highlightField!=null){
                        discussPost.setTitle(highlightField.getFragments()[0].toString());
                    }
                    HighlightField field = searchHit.getHighlightFields().get("content");
                    if (field!=null){
                        discussPost.setContent(field.getFragments()[0].toString());
                    }
                    list.add(discussPost);

                }

                return new AggregatedPageImpl(list,pageable,hit.getTotalHits(),response.getAggregations(),response.getScrollId(),hit.getMaxScore());
            }

            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
                return null;
            }

        });
    }
}
